package services

import (
	"bytes"
	"e_world_admin_backend/config"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"github.com/buger/jsonparser"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

type User struct {
	Name string   `json:"name"`
	Role []string `json:"role"`
}

func Login(c *gin.Context) {
	data, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		log.Println("ioutil read body error:" + err.Error())
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 2,
			"msg":  "request error",
		})
		return
	}
	// fmt.Println("data: ", string(data))
	// fmt.Println(c.GetHeader("Content-Type"))

	userName, err := jsonparser.GetString(data, "user_name")
	if err != nil {
		log.Println("json get user_name error:" + err.Error())
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 2,
			"msg":  "request user_name error",
		})
		return
	}

	password, err := jsonparser.GetString(data, "password")
	if err != nil {
		log.Println("json get password error:" + err.Error())
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 2,
			"msg":  "request password error",
		})
		return
	}

	user, err := authUser(userName, password)

	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code": 2,
			"msg":  "auth error",
		})
		return
	}

	theUser := UserData{
		UserName: user.Name,
		UserRole: user.Role,
	}

	// 创建token
	claims := CustomClaims{
		UserData: theUser,
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix() - 1000,       // 签名生效时间
			ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 一周
			Issuer:    "sherlock",                     // 签名的发行者
		},
	}
	token, err := myJwt.CreateToken(claims)
	if err != nil {
		log.Println("get token error: " + err.Error())
		c.JSON(http.StatusInternalServerError, gin.H{
			"code": 1,
			"msg":  "get token error",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "success",
		"data": gin.H{
			"role":  user.Role,
			"token": token,
		},
	})
}

func authUser(username string, password string) (user User, err error) {
	query := []byte(fmt.Sprintf(`{"query": "query {checkUserPassword(name: \"%s\", password: \"%s\") {name,role {name},}}"}`, username, password)) // 这里不能设置多行字符串
	//fmt.Println("query:", string(query))
	resp, err := postDgraph(query)
	if err != nil {
		log.Println("post dgraph error: " + err.Error())
		return
	}
	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("ioutil error: " + err.Error())
		return
	}
	fmt.Println("content: ", string(content))

	name, err := jsonparser.GetString(content, "data", "checkUserPassword", "name")
	if err != nil {
		log.Println("json get name error:" + err.Error())
		return
	}
	user.Name = name

	_, err = jsonparser.ArrayEach(content, func(value []byte, dataType jsonparser.ValueType, offset int, theErr error) {
		roleName, newErr := jsonparser.GetString(value, "name")
		if newErr != nil {
			err = newErr
			return
		}
		user.Role = append(user.Role, roleName)
	}, "data", "checkUserPassword", "role")
	if err != nil {
		log.Println("json get role error:" + err.Error())
		return
	}
	return
}

func postDgraph(data []byte) (*http.Response, error) {
	resp, err := http.Post(config.RequestUrl, "application/json", bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	return resp, nil
}
